package com.zerone.pay.trade.web.controller;

import com.acooly.core.common.boot.Apps;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.demo.trade.config.Configs;
import com.google.common.collect.Maps;
import com.zerone.pay.gateway.WXPayConfigMore;
import com.zerone.pay.trade.enums.PayMethodEnum;
import com.zerone.pay.trade.web.AccessTokenResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.sword.lang.HttpUtils;
import org.sword.wechat4j.exception.WeChatException;
import org.sword.wechat4j.util.WeChatUtil;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;

/**
 * @author 木鱼 muyu@yiji.com
 */
@Controller
@RequestMapping({"/cashier/"})
public class CashierController {


    protected static final Logger logger = LoggerFactory
            .getLogger(CashierController.class);

    @Autowired
    private AlipayClient alipayClient;

    @Autowired
    private WXPayConfigMore wxPayConfigMore;

    private String callbackUrl = Apps.getEnvironment().getProperty("pay.domain.name")+"cashier/aliCallBack";

	protected static final String USER_CODE_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?";

	private static final String TOKEN_AUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=";

    private static Map cache = Maps.newConcurrentMap();

    public CashierController() throws UnsupportedEncodingException {
    }

    @RequestMapping("/{partnerId}")
    public String cashier(@RequestHeader(value=HttpHeaders.USER_AGENT) String userAgent, @PathVariable String partnerId, Model model,HttpServletRequest request)
            throws AlipayApiException, UnsupportedEncodingException {
//
        request.getSession(true).setAttribute("partnerId",partnerId);
        if(userAgent.contains("AlipayClient")){
            String aliAuthUrl = getAliAuthUrl(partnerId);
            return "redirect:"+aliAuthUrl;
        }else if(userAgent.contains("MicroMessenger")){
            String wxCodeUrl=getWxCodeUrl(partnerId);
            return "redirect:"+wxCodeUrl;
        }else{
            model.addAttribute("msg","目前仅支持支付宝/微信客户端扫码支付");
            return "notSupport";
        }
    }

    /**
     * 接收支付宝回调回来的数据
     * @param authCode
     * @param appId
     * @param request
     * @return
     * @throws AlipayApiException
     */
    @RequestMapping("aliCallBack/{partnerId}")
    public String aliCallBack(@RequestParam(name = "auth_code") String authCode,
                              @PathVariable String partnerId,@RequestParam(name = "app_id") String appId,HttpServletRequest request,Model model)
            throws AlipayApiException {
        logger.info("收到支付宝回调 authCode={}",authCode);
//        if(cache.containsKey(authCode)){
//            cache.remove(authCode);
//            return null;
//        }else{
//            cache.put(authCode,authCode);
//        }

        //1.校验请求参数是否合法
        if(!Configs.getAppid().equals(appId)){
           throw new IllegalArgumentException("appId不对,非法回调");
        }
//        if(!AlipaySignature
//                .rsaCheckV1(request.getParameterMap().entrySet().stream().collect(
//                        Collectors.toMap(o -> o.getKey(), o -> o.getValue()[0])), Configs.getAlipayPublicKey(),  "utf-8", Configs.getSignType())){
//            throw new IllegalArgumentException("签名验证不通过");
//        }
        //2.转换成UseId
        AlipaySystemOauthTokenRequest alipaySystemOauthTokenRequest = new AlipaySystemOauthTokenRequest();
        alipaySystemOauthTokenRequest.setCode(authCode);
        alipaySystemOauthTokenRequest.setGrantType("authorization_code");
            AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(alipaySystemOauthTokenRequest);
            logger.info("转换userId，请求参数={},出参={}",alipaySystemOauthTokenRequest,oauthTokenResponse
                    );
        model.addAttribute("payMethod", PayMethodEnum.ali_code.code());
        model.addAttribute("userId",oauthTokenResponse.getUserId());
        model.addAttribute("partnerId",partnerId);
        model.addAttribute("payType","一码多付");
        return "cashierAlipay";
    }


	/**
	 * 接收微信回调回来的数据
	 * @param code
	 * @param appId
	 * @param request
	 * @return
	 * @throws AlipayApiException
	 */
	@RequestMapping("wechatCallBack")
	public String wechatCallBack(@RequestParam(name = "code") String code,
							  @RequestParam("state") String partnerId,String appId,HttpServletRequest request,Model model)
			throws WeChatException {
		logger.info("收到微信回调 authCode={},state={}",code,partnerId);
		//1.获取token
		String url = buildAppCodeToTokenUrl(code);
		logger.info("code转换openid，",url);
		String resStr = HttpUtils.get(url);
		logger.info("code转换openid，入参 url={},出参={}",url,resStr);
		WeChatUtil.isSuccess(resStr);
		AccessTokenResult accessToken = JSONObject.parseObject(resStr, AccessTokenResult.class);
		model.addAttribute("payMethod", PayMethodEnum.wechat_code.code());
		model.addAttribute("userId",accessToken.getOpenId());
		model.addAttribute("partnerId",partnerId);
		model.addAttribute("payType","一码多付");
		return "cashier";
	}

    private String getAliAuthUrl(String partnerId) throws UnsupportedEncodingException {
            return   Apps.getEnvironment().getProperty("alipay.authbase.url")+"?app_id=" + Configs.getAppid() + "&"
			  + "scope=auth_base&redirect_uri=" + URLEncoder.encode(callbackUrl+"/"+partnerId,"utf-8");

    }

    private String getWxCodeUrl(String partnerId) throws UnsupportedEncodingException {

		String URL_SUFFIX = "&response_type=code&scope=snsapi_base&state="+partnerId+"#wechat_redirect";
		String url = TOKEN_AUTH_URL+ wxPayConfigMore.getAppID()
					 + "&redirect_uri="+
		URLEncoder.encode(Apps.getEnvironment().getProperty("pay.domain.name")+"cashier/wechatCallBack","utf-8" )+URL_SUFFIX;
		return url;
	}


	/**
	 * 微信 code换token
	 * @param code
	 * @return
	 */
	protected String buildAppCodeToTokenUrl(String code) {
		StringBuilder urlBuilder = new StringBuilder(USER_CODE_TOKEN_URL);
		urlBuilder.append("appid=").append(wxPayConfigMore.getAppID());
		urlBuilder.append("&secret=").append(wxPayConfigMore.getAppSecret());
		urlBuilder.append("&code=").append(code);
		urlBuilder.append("&grant_type=").append("authorization_code");
		return urlBuilder.toString();
	}
}
